package com.dubious.interview.euler;

import java.util.HashMap;
import java.util.Map;

/**
 * If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3
 * + 5 + 4 + 4 = 19 letters used in total.
 * 
 * If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many
 * letters would be used?
 * 
 * 
 * NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and forty-two) contains 23
 * letters and 115 (one hundred and fifteen) contains 20 letters. The use of "and" when writing out
 * numbers is in compliance with British usage. *
 */
public class Problem17 {

    private static Map<Integer, String> digits = new HashMap<Integer, String>();
    static {
        digits.put(0, "");
        digits.put(1, "one");
        digits.put(2, "two");
        digits.put(3, "three");
        digits.put(4, "four");
        digits.put(5, "five");
        digits.put(6, "six");
        digits.put(7, "seven");
        digits.put(8, "eight");
        digits.put(9, "nine");
    }

    private static Map<Integer, String> tens = new HashMap<Integer, String>();
    static {
        tens.put(0, "");
        tens.put(1, "ten");
        tens.put(2, "twenty");
        tens.put(3, "thirty");
        tens.put(4, "forty");
        tens.put(5, "fifty");
        tens.put(6, "sixty");
        tens.put(7, "seventy");
        tens.put(8, "eighty");
        tens.put(9, "ninety");
    }

    private static Map<Integer, String> teens = new HashMap<Integer, String>();
    static {
        teens.put(10, "ten");
        teens.put(11, "eleven");
        teens.put(12, "twelve");
        teens.put(13, "thirteen");
        teens.put(14, "fourteen");
        teens.put(15, "fifteen");
        teens.put(16, "sixteen");
        teens.put(17, "seventeen");
        teens.put(18, "eighteen");
        teens.put(19, "nineteen");
    }

    public static void main(String[] args) {

        int n = 1000;
        int sumOfLetters = 0;

        // convert the numbers to their word equivalents and add
        for (int i = 1; i <= n; i++) {
            String writtenI = writeIntegerAsWord(i);
            System.out.println("writtenI: " + writtenI);
            sumOfLetters += stripSpaces(writtenI).length();
        }

        System.out.println("Sum of letters to " + n + ": " + sumOfLetters);
        // 21124
    }

    public static String writeIntegerAsWord(int value) {
        if (value > 1000) {
            throw new UnsupportedOperationException("Cannot currently write value " + value
                    + " as word");
        } else if (value == 1000) {
            return "one thousand";
        }

        StringBuilder valueAsString = new StringBuilder();
        if (value >= 100) {
            int digit = value / 100;
            valueAsString.append(digits.get(digit) + " hundred ");

            if (value % 100 != 0) {
                valueAsString.append("and ");
            }
        }

        value = value % 100;
        if (value >= 20) {
            // handle pattern "twenty", "twenty one", "twenty two", ..., "thirty", "thirty one", ...
            int digit = value / 10;
            valueAsString.append(tens.get(digit) + " ");

            value = value % 10;
            valueAsString.append(digits.get(value));
        } else if (value >= 10) {
            // handle values (10,19)
            valueAsString.append(teens.get(value));
        } else {
            // handle values (1,9)
            valueAsString.append(digits.get(value));
        }

        return valueAsString.toString();
    }

    public static String stripSpaces(String value) {
        return value.replace(" ", "");
    }
}
